﻿#include "common.h"
#include "FFmpegRecording.h"
#include <chrono>
#include <future>
#include <vector>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>

//alignas(4) enum class MyIODeviceType typeA;

// 录制类构造函数，初始化成员
FFmpegRecording::FFmpegRecording(QObject* parent)
    : QObject(parent)
{
}

// 录制类析构函数，自动清理资源
FFmpegRecording::~FFmpegRecording() {
    cleanup();
}

// 录制指定输出设备（通过WASAPI loopback）并编码为AAC
// device_id: output_device_list_中"driver"字段
// out_file: 输出AAC文件路径
// sample_rate/channels: 采样率/声道数
bool FFmpegRecording::record_output_device_aac(const std::string& device_id, const std::string& out_file, int sample_rate, int channels)
{
    cleanup(); // 清理之前的资源

    // 初始化COM库
    HRESULT hr = CoInitialize(nullptr);
    if (FAILED(hr)) { // 检查COM库初始化是否成功
        qDebug() << "COM库初始化失败, hr=" << hr;
        return false; // 初始化失败，返回 false
    }

    // 创建设备枚举器实例，用于查找音频设备
    IMMDeviceEnumerator* pEnum = nullptr;
    hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pEnum));
    if (FAILED(hr)) { // 检查设备枚举器创建是否成功
        qDebug() << "创建设备枚举器失败, hr=" << hr;
        CoUninitialize(); // 反初始化COM库
        return false; // 创建失败，返回 false
    }

    // 根据设备 ID 查找指定的音频输出设备
    IMMDevice* pDevice = nullptr;
    // 转化为 wstring，以便使用 GetDevice 接口
#if defined(_MSVC_LANG) && _MSVC_LANG < 201703 // C++17 以下标准
    // 创建一个转换器，这里 C++17 标准标准已移除
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
    std::wstring wdevice_id = converter.from_bytes(device_id); /* = QString::fromStdString(device_id).toStdWString();*/
#else // C++17 及以上标准
    std::wstring wdevice_id = str2wstr(device_id);
#endif
    hr = pEnum->GetDevice(wdevice_id.c_str(), &pDevice);
    if (FAILED(hr)) { // 检查设备查找是否成功
        qDebug() << "查找设备失败, hr=" << hr;
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化 COM 库
        return false; // 查找失败，返回 false
    }

    // 激活 AudioClient 以进行音频采集
    IAudioClient* pAudioClient = nullptr;
    hr = pDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void**)&pAudioClient);
    if (FAILED(hr)) { // 检查 AudioClient 激活是否成功
        qDebug() << "激活 AudioClient 失败, hr=" << hr;
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化 COM 库
        return false; // 激活失败，返回 false
    }

    // 获取设备的混合格式（原生格式）
    WAVEFORMATEX* pwfx = nullptr;
    hr = pAudioClient->GetMixFormat(&pwfx);
    if (FAILED(hr)) { // 检查格式获取是否成功
        qDebug() << "获取设备混合格式失败, hr=" << hr;
        pAudioClient->Release(); // 释放 AudioClient
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化 COM 库
        return false; // 获取格式失败，返回 false
    }
    // 打印设备原生支持的采样率和声道数
    qDebug() << "设备原生采样率=" << pwfx->nSamplesPerSec << ", 声道=" << pwfx->nChannels << ", 位宽=" << pwfx->wBitsPerSample;

    // 检查采样率和声道数是否兼容
    // 采集参数（设备原生）与目标参数（函数参数）分离，始终以设备原生参数采集，后续重采样为目标参数
    if (pwfx->nSamplesPerSec != sample_rate || pwfx->nChannels != (WORD)channels) {
        qDebug() << "警告：请求的采样率/声道数与设备不兼容，尝试使用设备原生格式采集，后续重采样";
        // 不要直接修改 pwfx，后续用 FFmpeg 重采样
    }

    // ========== 事件驱动采集优化开始 ==========
    // 创建事件句柄，用于事件驱动采集，提升音频质量，减少杂音
    HANDLE hCaptureEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
    if (!hCaptureEvent) {
        qDebug() << "创建事件句柄失败";
        CoTaskMemFree(pwfx);
        pAudioClient->Release();
        pDevice->Release();
        pEnum->Release();
        CoUninitialize();
        return false;
    }
    // 先初始化 AudioClient 为 loopback 采集模式 + 事件驱动
    hr = pAudioClient->Initialize(
        AUDCLNT_SHAREMODE_SHARED,
        AUDCLNT_STREAMFLAGS_LOOPBACK | AUDCLNT_STREAMFLAGS_EVENTCALLBACK, // 事件驱动
        0, 0, pwfx, nullptr);
    if (FAILED(hr)) {
        qDebug() << "AudioClient初始化失败, hr=" << hr << "，请确认设备未被独占或参数兼容";
        CloseHandle(hCaptureEvent);
        CoTaskMemFree(pwfx);
        pAudioClient->Release();
        pDevice->Release();
        pEnum->Release();
        CoUninitialize();
        return false;
    }
    // 再设置事件回调
    hr = pAudioClient->SetEventHandle(hCaptureEvent);
    if (FAILED(hr)) {
        qDebug() << "设置事件回调失败, hr=" << hr;
        CloseHandle(hCaptureEvent);
        CoTaskMemFree(pwfx);
        pAudioClient->Release();
        pDevice->Release();
        pEnum->Release();
        CoUninitialize();
        return false;
    }
    // ========== 事件驱动采集优化结束 ==========

    // 获取 CaptureClient 用于从 AudioClient 获取音频数据
    IAudioCaptureClient* pCaptureClient = nullptr;
    hr = pAudioClient->GetService(__uuidof(IAudioCaptureClient), (void**)&pCaptureClient);
    if (FAILED(hr)) { // 检查 CaptureClient 获取是否成功
        qDebug() << "获取 CaptureClient 失败, hr=" << hr;
        pAudioClient->Stop(); // 停止 AudioClient
        CloseHandle(hCaptureEvent); // 释放事件句柄
        CoTaskMemFree(pwfx); // 释放混合格式
        pAudioClient->Release(); // 释放 AudioClient
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化COM库
        return false; // 获取 CaptureClient 失败，返回false
    }

    // 启动 AudioClient 进行音频采集
    hr = pAudioClient->Start();
    if (FAILED(hr)) { // 检查启动是否成功
        qDebug() << "AudioClient启动失败, hr=" << hr;
        pCaptureClient->Release(); // 释放 CaptureClient
        CloseHandle(hCaptureEvent); // 释放事件句柄
        CoTaskMemFree(pwfx); // 释放混合格式
        pAudioClient->Release(); // 释放 AudioClient
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化COM库
        return false; // 启动失败，返回false
    }
    qDebug() << "WASAPI采集已启动，进入主循环... (事件驱动模式)"; // 打印启动信息

    // 注册所有可用的AVDevice，并初始化网络支持
    avdevice_register_all();
    avformat_network_init();
    AVFormatContext* output_ctx = nullptr;
    // 分配输出格式上下文
    avformat_alloc_output_context2(&output_ctx, nullptr, nullptr, out_file.c_str());
    if (!output_ctx) { // 检查输出格式上下文分配是否成功
        qDebug() << "无法创建输出上下文";
        avformat_network_deinit(); // 反初始化网络支持
        CloseHandle(hCaptureEvent); // 释放事件句柄
        CoTaskMemFree(pwfx); // 释放混合格式
        pCaptureClient->Release(); // 释放 CaptureClient
        pAudioClient->Stop(); // 停止 AudioClient
        pAudioClient->Release(); // 释放 AudioClient
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化COM库
        return false; // 分配失败，返回false
    }
    // 查找 AAC 编码器
    const AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
    if (!codec) { // 检查编码器查找是否成功
        qDebug() << "未找到AAC编码器";
        avformat_free_context(output_ctx); // 释放格式上下文
        avformat_network_deinit(); // 反初始化网络支持
        CloseHandle(hCaptureEvent); // 释放事件句柄
        CoTaskMemFree(pwfx); // 释放混合格式
        pCaptureClient->Release(); // 释放 CaptureClient
        pAudioClient->Stop(); // 停止 AudioClient
        pAudioClient->Release(); // 释放 AudioClient
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化COM库
        return false; // 查找失败，返回false
    }
    // 创建新的输出流
    AVStream* out_stream = avformat_new_stream(output_ctx, codec);
    // 分配编码器上下文
    AVCodecContext* enc_ctx = avcodec_alloc_context3(codec);
    if (!out_stream || !enc_ctx) { // 检查流和上下文分配是否成功
        qDebug() << "创建输出流或分配编码器上下文失败";
        avcodec_free_context(&enc_ctx); // 释放编码器上下文（如果已分配）
        avformat_free_context(output_ctx); // 释放格式上下文
        avformat_network_deinit(); // 反初始化网络支持
        CloseHandle(hCaptureEvent); // 释放事件句柄
        CoTaskMemFree(pwfx); // 释放混合格式
        pCaptureClient->Release(); // 释放 CaptureClient
        pAudioClient->Stop(); // 停止 AudioClient
        pAudioClient->Release(); // 释放 AudioClient
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化COM库
        return false; // 创建失败，返回false
    }

    // 查询编码器支持的采样格式，优先选择 AV_SAMPLE_FMT_FLTP
    // 新增：打印编码器支持的采样格式，便于调试
    qDebug() << "AAC编码器支持的采样格式：";
#if LIBAVCODEC_VERSION_MAJOR < 60
    if (codec->sample_fmts) {
        const AVSampleFormat* p = codec->sample_fmts;
        while (*p != AV_SAMPLE_FMT_NONE) {
            qDebug() << av_get_sample_fmt_name(*p); // 打印采样格式名称
            ++p;
        }
    }
    // 如果你想强制输出S16格式，可以尝试如下设置（但AAC编码器通常不支持S16）
    // AVSampleFormat sample_fmt = AV_SAMPLE_FMT_S16;
    // 检查编码器是否支持S16
    AVSampleFormat sample_fmt = AV_SAMPLE_FMT_FLTP; // 默认格式
    if (codec->sample_fmts) {
        const AVSampleFormat* p = codec->sample_fmts;
        bool support_s16 = false;
        while (*p != AV_SAMPLE_FMT_NONE) {
            if (*p == AV_SAMPLE_FMT_S16) {
                support_s16 = true;
                break;
            }
            ++p;
        }
        if (support_s16) {
            sample_fmt = AV_SAMPLE_FMT_S16; // 使用S16格式
            qDebug() << "AAC编码器支持S16，使用S16输出"; // 打印信息
        } else {
            qDebug() << "AAC编码器不支持S16，使用默认FLTP输出"; // 打印信息
        }
    }
#else
    // FFmpeg 6.0及以上，sample_fmts已废弃，直接用默认FLTP
    AVSampleFormat sample_fmt = AV_SAMPLE_FMT_FLTP;
    qDebug() << "FFmpeg 6.0+，默认使用FLTP"; // 打印信息
#endif
    enc_ctx->sample_fmt = sample_fmt; // 设置样本格式
    enc_ctx->sample_rate = sample_rate; // 设置目标采样率
    av_channel_layout_default(&enc_ctx->ch_layout, channels); // 设置目标声道数
    enc_ctx->bit_rate = 128000; // 设置比特率
    enc_ctx->time_base = { 1, sample_rate }; // 设置时间基准
    out_stream->time_base = enc_ctx->time_base; // 设置输出流的时间基准
    if (output_ctx->oformat->flags & AVFMT_GLOBALHEADER)
        enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // 设置全局头标志
    // 打开编码器
    int ret = avcodec_open2(enc_ctx, codec, nullptr);
    if (ret < 0) { // 检查编码器打开是否成功
        qDebug() << "打开编码器失败, ret=" << ret << ", 采样格式=" << enc_ctx->sample_fmt; // 打印错误信息
        avcodec_free_context(&enc_ctx); // 释放编码器上下文
        avformat_free_context(output_ctx); // 释放格式上下文
        avformat_network_deinit(); // 反初始化网络支持
        CloseHandle(hCaptureEvent); // 释放事件句柄
        CoTaskMemFree(pwfx); // 释放混合格式
        pCaptureClient->Release(); // 释放 CaptureClient
        pAudioClient->Stop(); // 停止 AudioClient
        pAudioClient->Release(); // 释放 AudioClient
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化COM库
        return false; // 打开失败，返回false
    }
    // 设置输出流的参数
    avcodec_parameters_from_context(out_stream->codecpar, enc_ctx);
    // 如果输出格式支持文件操作，打开输出文件
    if (!(output_ctx->oformat->flags & AVFMT_NOFILE)) {
        if (avio_open(&output_ctx->pb, out_file.c_str(), AVIO_FLAG_WRITE) < 0) { // 打开输出文件
            qDebug() << "无法打开输出文件";
            avcodec_free_context(&enc_ctx);  // 关闭编码器
            avcodec_free_context(&enc_ctx); // 释放编码器上下文
            avformat_free_context(output_ctx); // 释放格式上下文
            avformat_network_deinit(); // 反初始化网络支持
            CloseHandle(hCaptureEvent); // 释放事件句柄
            CoTaskMemFree(pwfx); // 释放混合格式
            pCaptureClient->Release(); // 释放 CaptureClient
            pAudioClient->Stop(); // 停止 AudioClient
            pAudioClient->Release(); // 释放 AudioClient
            pDevice->Release(); // 释放设备实例
            pEnum->Release(); // 释放设备枚举器
            CoUninitialize(); // 反初始化COM库
            return false; // 打开失败，返回false
        }
    }
    // 写入文件头
    avformat_write_header(output_ctx, nullptr);

    // 分配 SwrContext 用于重采样
    SwrContext* swr_ctx = swr_alloc();
    if (!swr_ctx) { // 检查 SwrContext 分配是否成功
        qDebug() << "分配 SwrContext 失败";
        avcodec_free_context(&enc_ctx);  // 关闭编码器
        avcodec_free_context(&enc_ctx); // 释放编码器上下文
        avformat_free_context(output_ctx); // 释放格式上下文
        if (!(output_ctx->oformat->flags & AVFMT_NOFILE) && output_ctx->pb) {
            avio_closep(&output_ctx->pb); // 关闭输出文件
        }
        avformat_network_deinit(); // 反初始化网络支持
        CloseHandle(hCaptureEvent); // 释放事件句柄
        CoTaskMemFree(pwfx); // 释放混合格式
        pCaptureClient->Release(); // 释放 CaptureClient
        pAudioClient->Stop(); // 停止 AudioClient
        pAudioClient->Release(); // 释放 AudioClient
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化COM库
        return false; // 分配失败，返回false
    }

    // 使用 av_channel_layout_default 初始化输入声道布局，避免手动赋值导致不兼容
    AVChannelLayout in_ch_layout;
    av_channel_layout_default(&in_ch_layout, pwfx->nChannels); // 用设备原生声道数初始化

    // 判断 WASAPI 输出格式
    AVSampleFormat wasapi_fmt = AV_SAMPLE_FMT_S16;
    if (pwfx->wBitsPerSample == 32) {
        // WAVE_FORMAT_IEEE_FLOAT = 3
        wasapi_fmt = (pwfx->wFormatTag == 3) ? AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S32; // 设置为32位浮点或有符号整数
    } else if (pwfx->wBitsPerSample == 16) {
        wasapi_fmt = AV_SAMPLE_FMT_S16; // 设置为16位有符号整数
    }

    // 设置重采样参数
    av_opt_set_chlayout(swr_ctx, "in_chlayout", &in_ch_layout, 0); // 设置输入声道布局
    av_opt_set_int(swr_ctx, "in_sample_rate", pwfx->nSamplesPerSec, 0); // 设置输入采样率
    av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", wasapi_fmt, 0); // 设置输入样本格式
    av_opt_set_chlayout(swr_ctx, "out_chlayout", &enc_ctx->ch_layout, 0); // 设置输出声道布局
    av_opt_set_int(swr_ctx, "out_sample_rate", enc_ctx->sample_rate, 0); // 设置输出采样率
    av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", enc_ctx->sample_fmt, 0); // 设置输出样本格式
    // 初始化重采样上下文
    if ((ret = swr_init(swr_ctx)) < 0) {
        qDebug() << "初始化重采样失败, ret=" << ret << "，请检查输入/输出采样格式、声道数、采样率参数是否兼容。"; // 打印错误信息
        swr_free(&swr_ctx); // 释放 SwrContext
        avcodec_free_context(&enc_ctx);  // 关闭编码器
        avcodec_free_context(&enc_ctx); // 释放编码器上下文
        avformat_free_context(output_ctx); // 释放格式上下文
        if (!(output_ctx->oformat->flags & AVFMT_NOFILE) && output_ctx->pb) {
            avio_closep(&output_ctx->pb); // 关闭输出文件
        }
        avformat_network_deinit(); // 反初始化网络支持
        CloseHandle(hCaptureEvent); // 释放事件句柄
        CoTaskMemFree(pwfx); // 释放混合格式
        pCaptureClient->Release(); // 释放 CaptureClient
        pAudioClient->Stop(); // 停止 AudioClient
        pAudioClient->Release(); // 释放 AudioClient
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化COM库
        return false; // 初始化失败，返回false
    }

    // 采集与编码分离
    start_pts_ = 0; // 设置起始时间戳
    recording_ = true; // 设置录音标志为true

    // 分配编码用的AVFrame和AVPacket对象，供主循环使用
    AVFrame* frame = av_frame_alloc();
    if (!frame) { // 检查AVFrame分配是否成功
        qDebug() << "av_frame_alloc failed (thread)";
        swr_free(&swr_ctx); // 释放 SwrContext
        avcodec_free_context(&enc_ctx);  // 关闭编码器
        avcodec_free_context(&enc_ctx); // 释放编码器上下文
        avformat_free_context(output_ctx); // 释放格式上下文
        if (!(output_ctx->oformat->flags & AVFMT_NOFILE) && output_ctx->pb) {
            avio_closep(&output_ctx->pb); // 关闭输出文件
        }
        avformat_network_deinit(); // 反初始化网络支持
        CloseHandle(hCaptureEvent); // 释放事件句柄
        CoTaskMemFree(pwfx); // 释放混合格式
        pCaptureClient->Release(); // 释放 CaptureClient
        pAudioClient->Stop(); // 停止 AudioClient
        pAudioClient->Release(); // 释放 AudioClient
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化COM库
        return false; // 分配失败，返回false
    }
    frame->nb_samples = enc_ctx->frame_size; // 设置样本数量
    frame->format = enc_ctx->sample_fmt; // 设置样本格式
    av_channel_layout_copy(&frame->ch_layout, &enc_ctx->ch_layout); // 复制声道布局
    frame->sample_rate = enc_ctx->sample_rate; // 设置采样率
    // 分配音频帧的数据缓冲区
    if (av_frame_get_buffer(frame, 0) < 0) {
        qDebug() << "av_frame_get_buffer failed (thread)";
        av_frame_free(&frame); // 释放AVFrame
        swr_free(&swr_ctx); // 释放 SwrContext
        avcodec_free_context(&enc_ctx);  // 关闭编码器
        avcodec_free_context(&enc_ctx); // 释放编码器上下文
        avformat_free_context(output_ctx); // 释放格式上下文
        if (!(output_ctx->oformat->flags & AVFMT_NOFILE) && output_ctx->pb) {
            avio_closep(&output_ctx->pb); // 关闭输出文件
        }
        avformat_network_deinit(); // 反初始化网络支持
        CloseHandle(hCaptureEvent); // 释放事件句柄
        CoTaskMemFree(pwfx); // 释放混合格式
        pCaptureClient->Release(); // 释放 CaptureClient
        pAudioClient->Stop(); // 停止 AudioClient
        pAudioClient->Release(); // 释放 AudioClient
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化COM库
        return false; // 分配失败，返回false
    }
    // 分配AVPacket对象用于存储编码后的数据
    AVPacket* pkt = av_packet_alloc();
    if (!pkt) { // 检查AVPacket分配是否成功
        qDebug() << "av_packet_alloc failed (thread)";
        av_frame_free(&frame); // 释放AVFrame
        swr_free(&swr_ctx); // 释放 SwrContext
        avcodec_free_context(&enc_ctx);  // 关闭编码器
        avcodec_free_context(&enc_ctx); // 释放编码器上下文
        avformat_free_context(output_ctx); // 释放格式上下文
        if (!(output_ctx->oformat->flags & AVFMT_NOFILE) && output_ctx->pb) {
            avio_closep(&output_ctx->pb); // 关闭输出文件
        }
        avformat_network_deinit(); // 反初始化网络支持
        CloseHandle(hCaptureEvent); // 释放事件句柄
        CoTaskMemFree(pwfx); // 释放混合格式
        pCaptureClient->Release(); // 释放 CaptureClient
        pAudioClient->Stop(); // 停止 AudioClient
        pAudioClient->Release(); // 释放 AudioClient
        pDevice->Release(); // 释放设备实例
        pEnum->Release(); // 释放设备枚举器
        CoUninitialize(); // 反初始化COM库
        return false; // 分配失败，返回false
    }

    // 分配缓冲区参数
    int in_channels = pwfx->nChannels; // 输入声道数
    int in_bytes_per_sample = pwfx->wBitsPerSample / 8; // 每个样本的字节数
    int in_frame_bytes = enc_ctx->frame_size * in_channels * in_bytes_per_sample; // 一帧音频的字节数
    int out_frame_samples = enc_ctx->frame_size; // 一帧音频的样本数
    std::vector<uint8_t> pcm_buffer; // PCM音频数据缓冲区

    // 主采集循环（事件驱动，提升音频采集质量，减少杂音）
    while (recording_) {
        DWORD waitResult = WaitForSingleObject(hCaptureEvent, 2000); // 最多等2秒
        if (waitResult != WAIT_OBJECT_0) {
            qDebug() << "等待音频事件超时或失败";
            break;
        }
        UINT32 packetLength = 0;
        hr = pCaptureClient->GetNextPacketSize(&packetLength);
        if (FAILED(hr) || packetLength == 0) {
            continue;
        }
        BYTE* pData = nullptr;
        UINT32 numFramesAvailable = 0;
        DWORD flags = 0;
        hr = pCaptureClient->GetBuffer(&pData, &numFramesAvailable, &flags, nullptr, nullptr);
        if (FAILED(hr)) {
            qDebug() << "获取音频缓冲区失败, hr=" << hr;
            break;
        }
        if (flags & AUDCLNT_BUFFERFLAGS_SILENT) {
            pcm_buffer.insert(pcm_buffer.end(), numFramesAvailable * in_channels * in_bytes_per_sample, 0);
        } else {
            pcm_buffer.insert(pcm_buffer.end(), pData, pData + numFramesAvailable * in_channels * in_bytes_per_sample);
        }
        pCaptureClient->ReleaseBuffer(numFramesAvailable);
        while ((int)pcm_buffer.size() >= in_frame_bytes) {
            const uint8_t* in_data[1] = { pcm_buffer.data() };
            int converts = swr_convert(swr_ctx, frame->data, out_frame_samples, in_data, out_frame_samples);
            frame->pts = start_pts_++;
            if (avcodec_send_frame(enc_ctx, frame) == 0) {
                while (avcodec_receive_packet(enc_ctx, pkt) == 0) {
                    pkt->stream_index = out_stream->index;
                    av_packet_rescale_ts(pkt, enc_ctx->time_base, out_stream->time_base);
                    av_interleaved_write_frame(output_ctx, pkt);
                    av_packet_unref(pkt);
                }
            }
            pcm_buffer.erase(pcm_buffer.begin(), pcm_buffer.begin() + in_frame_bytes);
        }
    }

    // 录音结束后 flush 剩余数据
    while (!pcm_buffer.empty()) {
        int remain_samples = (int)pcm_buffer.size() / (in_channels * in_bytes_per_sample); // 计算剩余样本数
        int fill_samples = std::min(remain_samples, out_frame_samples); // 计算填充样本数
        int in_samples = fill_samples; // 计算实际输入样本数
        if (fill_samples <= 0)
            break; // 如果没有样本可处理，退出循环
        const uint8_t* in_data[1] = { pcm_buffer.data() };
        // 重采样到编码器格式
        swr_convert(swr_ctx, frame->data, fill_samples, in_data, in_samples);
        frame->nb_samples = fill_samples; // 设置音频帧的样本数量
        frame->pts = start_pts_++; // 设置音频帧的时间戳
        // 发送音频帧到编码器
        if (avcodec_send_frame(enc_ctx, frame) == 0) {
            // 接收编码后的数据包
            while (avcodec_receive_packet(enc_ctx, pkt) == 0) {
                pkt->stream_index = out_stream->index; // 设置数据包的流索引
                // 重缩放时间戳
                av_packet_rescale_ts(pkt, enc_ctx->time_base, out_stream->time_base);
                // 写入数据包到输出文件
                av_interleaved_write_frame(output_ctx, pkt);
                // 释放数据包
                av_packet_unref(pkt);
            }
        }
        // 移除已处理的数据
        pcm_buffer.erase(pcm_buffer.begin(), pcm_buffer.begin() + fill_samples * in_channels * in_bytes_per_sample);
    }

    // 9. 收尾
    av_write_trailer(output_ctx); // 写入文件尾
    av_frame_free(&frame); // 释放音频帧
    av_packet_free(&pkt); // 释放音频包
    swr_free(&swr_ctx); // 释放重采样上下文
    avcodec_free_context(&enc_ctx); // 释放编码器上下文
    if (!(output_ctx->oformat->flags & AVFMT_NOFILE) && output_ctx->pb) {
        avio_closep(&output_ctx->pb); // 关闭输出文件
    }
    avformat_free_context(output_ctx); // 释放格式上下文
    avformat_network_deinit(); // 反初始化网络支持

    pAudioClient->Stop(); // 停止 AudioClient
    pCaptureClient->Release(); // 释放 CaptureClient
    CoTaskMemFree(pwfx); // 释放混合格式
    pAudioClient->Release(); // 释放 AudioClient
    pDevice->Release(); // 释放设备实例
    pEnum->Release(); // 释放设备枚举器
    // 释放事件句柄，防止资源泄漏
    if (hCaptureEvent) {
        CloseHandle(hCaptureEvent);
    }
    CoUninitialize(); // 反初始化COM库
    return true; // 返回true表示成功
}

bool FFmpegRecording::record_microphone_aac(int sample_rate, int channels, const AVInputFormat* input_fmt, std::string& device_name)
{
    // 实时录制，从麦克风设备采集音频帧，转化为 AAC 编码的 AVFrame 放入麦克风音频帧队列
    AVFrame* frame = av_frame_alloc(); // 分配音频帧
    if (!frame) {
        qDebug() << "av_frame_alloc failed (thread)";
        return false;
    }
    AVDictionary* options = nullptr;
    int ret = avformat_open_input(&microphone_input_ctx_, device_name.c_str(), input_fmt, &options);
    if (ret < 0) {
        char errbuf[256];
        av_strerror(ret, errbuf, sizeof(errbuf));
        qDebug() << "无法打开音频输入设备:" << device_name.c_str() << "; 错误代码：" << ret << ", " << errbuf;
        return false;
    }
    if ((ret = avformat_find_stream_info(microphone_input_ctx_, nullptr)) < 0) {
        qDebug() << "无法获取输入流信息；错误代码：" << ret;
        return false;
    }
    int audio_stream_index = -1;
    for (unsigned i = 0; i < microphone_input_ctx_->nb_streams; ++i) {
        if (microphone_input_ctx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            audio_stream_index = i;
            break;
        }
    }
    if (audio_stream_index < 0) {
        qDebug() << "未找到音频流";
        return false;
    }

    // 2. 创建输出文件上下文
    avformat_alloc_output_context2(&microphone_output_ctx_, nullptr, nullptr, output_file_.c_str());
    if (!microphone_output_ctx_) {
        qDebug() << "无法创建输出上下文";
        return false;
    }

    // 3. 查找AAC编码器
    const AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
    if (!codec) {
        qDebug() << "未找到AAC编码器";
        return false;
    }
    microphone_out_stream_ = avformat_new_stream(microphone_output_ctx_, codec);
    if (!microphone_out_stream_) {
        qDebug() << "无法创建输出流";
        return false;
    }
    microphone_encoder_ctx_ = avcodec_alloc_context3(codec);
    // 查询编码器支持的采样格式，优先选择 AV_SAMPLE_FMT_FLTP
    // 新增：打印编码器支持的采样格式，便于调试
    qDebug() << "AAC编码器支持的采样格式：";
#if LIBAVCODEC_VERSION_MAJOR < 60
    if (codec->sample_fmts) {
        const AVSampleFormat* p = codec->sample_fmts;
        while (*p != AV_SAMPLE_FMT_NONE) {
            qDebug() << av_get_sample_fmt_name(*p);
            ++p;
        }
    }
    // 如果你想强制输出S16格式，可以尝试如下设置（但AAC编码器通常不支持S16）
    // AVSampleFormat sample_fmt = AV_SAMPLE_FMT_S16;
    // 检查编码器是否支持S16
    AVSampleFormat sample_fmt = AV_SAMPLE_FMT_FLTP; // 默认
    if (codec->sample_fmts) {
        const AVSampleFormat* p = codec->sample_fmts;
        bool support_s16 = false;
        while (*p != AV_SAMPLE_FMT_NONE) {
            if (*p == AV_SAMPLE_FMT_S16) {
                support_s16 = true;
                break;
            }
            ++p;
        }
        if (support_s16) {
            sample_fmt = AV_SAMPLE_FMT_S16;
            qDebug() << "AAC编码器支持S16，使用S16输出";
        }
        else {
            qDebug() << "AAC编码器不支持S16，使用默认FLTP输出";
        }
    }
#else
    // FFmpeg 6.0及以上，sample_fmts已废弃，直接用默认FLTP
    AVSampleFormat sample_fmt = AV_SAMPLE_FMT_FLTP;
    qDebug() << "FFmpeg 6.0+，默认使用FLTP";
#endif
    microphone_encoder_ctx_->sample_fmt = sample_fmt; // 选择支持的采样格式
    microphone_encoder_ctx_->sample_rate = sample_rate_;
    av_channel_layout_default(&microphone_encoder_ctx_->ch_layout, channels_);
    microphone_encoder_ctx_->bit_rate = 128000;
    microphone_encoder_ctx_->time_base = { 1, sample_rate_ };
    microphone_out_stream_->time_base = microphone_encoder_ctx_->time_base;
    if (microphone_output_ctx_->oformat->flags & AVFMT_GLOBALHEADER)
        microphone_encoder_ctx_->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    if (avcodec_open2(microphone_encoder_ctx_, codec, nullptr) < 0) {
        qDebug() << "无法打开AAC编码器";
        return false;
    }
    if ((ret = avcodec_parameters_from_context(microphone_out_stream_->codecpar, microphone_encoder_ctx_)) < 0) {
        qDebug() << "无法设置输出流参数; 错误代码：" << ret;
        return false;
    }

    // 4. 打开输出文件
    if (!(microphone_output_ctx_->oformat->flags & AVFMT_NOFILE)) {
        if (avio_open(&microphone_output_ctx_->pb, output_file_.c_str(), AVIO_FLAG_WRITE) < 0) {
            qDebug() << "无法打开输出文件";
            return false;
        }
    }
    if ((ret = avformat_write_header(microphone_output_ctx_, nullptr)) < 0) {
        qDebug() << "写入文件头失败; 错误代码：" << ret;
        return false;
    }

    // 5. 初始化重采样（如果输入采样格式与编码器不一致）
    AVCodecParameters* in_codecpar = microphone_input_ctx_->streams[audio_stream_index]->codecpar;
    microphone_swr_ctx_ = swr_alloc();
    if (!microphone_swr_ctx_) {
        qDebug() << "重采样分配失败";
        return false;
    }
    av_opt_set_chlayout(microphone_swr_ctx_, "in_chlayout", &in_codecpar->ch_layout, 0);
    av_opt_set_int(microphone_swr_ctx_, "in_sample_rate", in_codecpar->sample_rate, 0);
    av_opt_set_sample_fmt(microphone_swr_ctx_, "in_sample_fmt", (AVSampleFormat)in_codecpar->format, 0);
    av_opt_set_chlayout(microphone_swr_ctx_, "out_chlayout", &microphone_encoder_ctx_->ch_layout, 0);
    av_opt_set_int(microphone_swr_ctx_, "out_sample_rate", microphone_encoder_ctx_->sample_rate, 0);
    av_opt_set_sample_fmt(microphone_swr_ctx_, "out_sample_fmt", microphone_encoder_ctx_->sample_fmt, 0);
    if ((ret = swr_init(microphone_swr_ctx_)) < 0) {
        qDebug() << "重采样初始化失败; 错误代码：" << ret << "，请检查输入/输出采样格式、声道数、采样率参数是否兼容。";
        return false;
    }

    // 6. 分配帧和包
    microphone_frame_ = av_frame_alloc();
    if (!microphone_frame_) {
        qDebug() << "av_frame_alloc failed";
        return false;
    }
    microphone_frame_->nb_samples = microphone_encoder_ctx_->frame_size;
    microphone_frame_->format = microphone_encoder_ctx_->sample_fmt;
    av_channel_layout_copy(&microphone_frame_->ch_layout, &microphone_encoder_ctx_->ch_layout);
    microphone_frame_->sample_rate = microphone_encoder_ctx_->sample_rate;
    if (av_frame_get_buffer(microphone_frame_, 0) < 0) {
        qDebug() << "av_frame_get_buffer failed";
        av_frame_free(&microphone_frame_);
        return false;
    }
    microphone_pkt_ = av_packet_alloc();
    if (!microphone_pkt_) {
        qDebug() << "av_packet_alloc failed";
        av_frame_free(&microphone_frame_);
        return false;
    }

    recording_ = true;
    paused_ = false;
    start_pts_ = 0;

    // 实时录制主循环（直到 stop_record 被调用）
    // 累积PCM数据，填满 frame_->nb_samples 再编码，避免只录制一小段
    std::vector<uint8_t> pcm_buffer;
    int bytes_per_sample = av_get_bytes_per_sample((AVSampleFormat)in_codecpar->format);
    int in_channels = in_codecpar->ch_layout.nb_channels;
    int frame_bytes = microphone_frame_->nb_samples * in_channels * av_get_bytes_per_sample((AVSampleFormat)microphone_encoder_ctx_->sample_fmt);
    int in_frame_bytes = microphone_frame_->nb_samples * in_channels * bytes_per_sample;
    while (recording_)
    {
        // 暂停时丢弃采集到的数据，防止暂停期间音频被录制到文件
        if (paused_) {
            AVPacket input_pkt;
            if ((ret = av_read_frame(microphone_input_ctx_, &input_pkt)) >= 0) {
                // 直接丢弃数据，不写入缓冲区和文件
                av_packet_unref(&input_pkt); // 传递指针
            }
            else {
                // 采集失败，退出循环
                break;
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 防止CPU占用过高
            continue;
        }
        // 还有一种思路是暂停时彻底关闭设备，重新打开，但这样可能会导致音频延迟，且逻辑复杂，所以暂时不采用，以后应该会用到；Audition就是这个方案
        if (!recording_)
            break; // 如果在暂停期间被停止，直接退出

        AVPacket input_pkt;
        if ((ret = av_read_frame(microphone_input_ctx_, &input_pkt)) < 0)
            break;
        // 累积采集到的PCM数据
        pcm_buffer.insert(pcm_buffer.end(), input_pkt.data, input_pkt.data + input_pkt.size);
        av_packet_unref(&input_pkt); // 传递指针
        // 只要 buffer 里数据够一帧就处理
        // 新增：只有frame_有效时才处理pcm_buffer，防止frame_为nullptr时崩溃
        while ((int)pcm_buffer.size() >= in_frame_bytes) {
            // 输入数据指针
            const uint8_t* in_data[1] = { pcm_buffer.data() };
            // 重采样到编码器格式
            swr_convert(microphone_swr_ctx_, microphone_frame_->data, microphone_frame_->nb_samples, in_data, microphone_frame_->nb_samples);
            microphone_frame_->pts = start_pts_++;
            if (avcodec_send_frame(microphone_encoder_ctx_, microphone_frame_) == 0) {
                while (avcodec_receive_packet(microphone_encoder_ctx_, microphone_pkt_) == 0) {
                    microphone_pkt_->stream_index = microphone_out_stream_->index;
                    av_packet_rescale_ts(microphone_pkt_, microphone_encoder_ctx_->time_base, microphone_out_stream_->time_base);
                    av_interleaved_write_frame(microphone_output_ctx_, microphone_pkt_);
                    av_packet_unref(microphone_pkt_);
                }
            }
            // 移除已处理的数据
            pcm_buffer.erase(pcm_buffer.begin(), pcm_buffer.begin() + in_frame_bytes);
        }
    }
    // 录音结束后 flush 剩余数据
    while (!pcm_buffer.empty()) {
        int remain_samples = (int)pcm_buffer.size() / (in_channels * bytes_per_sample);
        int fill_samples = std::min(remain_samples, microphone_frame_->nb_samples);
        int in_samples = fill_samples; // 计算实际输入采样数
        if (fill_samples <= 0)
            break;
        const uint8_t* in_data[1] = { pcm_buffer.data() };
        swr_convert(microphone_swr_ctx_, microphone_frame_->data, fill_samples, in_data, in_samples); // swr_convert 的输入采样数用 in_samples
        microphone_frame_->nb_samples = fill_samples;
        microphone_frame_->pts = start_pts_++;
        if (avcodec_send_frame(microphone_encoder_ctx_, microphone_frame_) == 0) {
            while (avcodec_receive_packet(microphone_encoder_ctx_, microphone_pkt_) == 0) {
                microphone_pkt_->stream_index = microphone_out_stream_->index;
                av_packet_rescale_ts(microphone_pkt_, microphone_encoder_ctx_->time_base, microphone_out_stream_->time_base);
                av_interleaved_write_frame(microphone_output_ctx_, microphone_pkt_);
                av_packet_unref(microphone_pkt_);
            }
        }
        pcm_buffer.erase(pcm_buffer.begin(), pcm_buffer.begin() + fill_samples * in_channels * bytes_per_sample);
    }
    av_write_trailer(microphone_output_ctx_);
    recording_ = false;
    // 关闭设备
    cleanup(MyIODeviceType::Microphone);
    return true;
}

// 主录制函数，支持实时录制、设备类型选择
bool FFmpegRecording::main_recording(int sample_rate, int channels, MyIODeviceType input_type)
{
    avdevice_register_all(); // 注册设备

    // 单设备录制
    const AVInputFormat* input_fmt = av_find_input_format("dshow");
    if (!input_fmt) {
        qDebug() << "未找到dshow输入格式";
        return false;
    }
    std::string device_name;
    // 使用传入参数 input_type，而不是成员变量 input_type_
    if (input_type == MyIODeviceType::Microphone) {
        device_name = "audio=" + get_default_device(MyIODeviceType::Microphone); // 麦克风
        return record_microphone_aac(sample_rate, channels, input_fmt, device_name);
    }
    else if (input_type == MyIODeviceType::Speaker) {
        // 声明并获取输出设备列表
        const auto& output_list = get_output_device_list();
        if (output_list.empty()) {
            qDebug() << "未找到可用的输出设备";
            return false;
        }
        std::string device_id = output_list[0].at("driver");
        record_output_device_aac(device_id, output_file_, sample_rate, channels);
        cleanup(input_type);
        return true;
    }

    // 关闭设备
    cleanup(input_type);
    return false;
}

// 辅助函数：混合录制
// 该函数将麦克风和扬声器的音频流采集并混合后编码为AAC，保存到同一输出文件
// 此实现为简单加和混音，未做音量归一化和溢出处理，实际项目可根据需求优化
// 这里即将实现


// 开始录音，支持实时录制、设备类型选择
bool FFmpegRecording::start_record(const std::string& out_file, int sample_rate, int channels, MyIODeviceType input_type, const std::string& file2)
{
    if (recording_) {
        qDebug() << "正在录音，请等待结束后再开始新的录音。";
        return false;
    }
    cleanup();
    output_file_ = out_file;
    sample_rate_ = sample_rate;
    channels_ = channels;
    input_type_ = input_type;
    if (!file2.empty())
        output_file_second_ = file2;
    recording_ = false;
    paused_ = false;

    // 线程安全处理
    if (microphone_queue_thread_.joinable())
        microphone_queue_thread_.join();
    if (microphone_save_thread_.joinable())
        microphone_save_thread_.join();

    if (input_type_ == MyIODeviceType::Microphone) {
        microphone_thread1_running_ = true;
        microphone_queue_thread_ = std::thread([this, out_file, sample_rate, channels]() {
            main_recording(sample_rate, channels, MyIODeviceType::Microphone);
            microphone_thread1_running_ = false;
        });
        return true;
    }
    else if (input_type_ == MyIODeviceType::Speaker) {
        microphone_thread1_running_ = true;
        microphone_queue_thread_ = std::thread([this, out_file, sample_rate, channels]() {
            main_recording(sample_rate, channels, MyIODeviceType::Speaker);
            microphone_thread1_running_ = false;
        });
        return true;
    }
    else if (input_type_ == MyIODeviceType::TwoFile) {
        // file2 必须有效
        if (output_file_second_.empty())
            return false;
        microphone_thread1_running_ = true;
        //microphone_thread2_running_ = true;
        microphone_queue_thread_ = std::thread([this, sample_rate, channels]() {
            main_recording(sample_rate, channels, MyIODeviceType::Microphone);
            microphone_thread1_running_ = false;
        });
        microphone_save_thread_ = std::thread([this, sample_rate, channels]() {
            main_recording(sample_rate, channels, MyIODeviceType::Speaker);
            //microphone_thread2_running_ = false;
        });
        return true;
    }
    
    return false;
}

// 停止录音
void FFmpegRecording::stop_record() {
    recording_ = false;
    if (microphone_queue_thread_.joinable())
        microphone_queue_thread_.join();
    if (microphone_save_thread_.joinable())
        microphone_save_thread_.join();
}

// 暂停录音
void FFmpegRecording::pause_record() {
    // 只有在录音线程还在运行且未暂停时才允许暂停
    // 注意：暂停时frame_对象仍然存在，只有录音线程结束后才会被cleanup释放
    if (recording_ && !paused_) {
        paused_ = true;
    }
}

// 恢复录音
void FFmpegRecording::resume_record() {
    // 只有在录音线程还在运行且已暂停时才允许恢复
    // 注意：如果frame_为nullptr，说明录音线程已结束并释放资源，不能恢复
    if (recording_ && paused_) {
        if (microphone_frame_ == nullptr) {
            qDebug() << "无法恢复录音：frame_已被释放，录音线程已结束。请重新开始录音。";
            return;
        }
        paused_ = false;
    }
}

// 是否正在录音
bool FFmpegRecording::is_recording() const {
    return recording_;
}

// 是否处于暂停状态
bool FFmpegRecording::is_paused() const {
    return paused_;
}

// 清理资源
void FFmpegRecording::cleanup(MyIODeviceType input_type)
{
    if (input_type == MyIODeviceType::Microphone || input_type == MyIODeviceType::MicrophoneAndSpeaker) {
        if (microphone_pkt_) {
            av_packet_free(&microphone_pkt_);
            microphone_pkt_ = nullptr;
        }
        if (microphone_frame_) {
            av_frame_free(&microphone_frame_);
            microphone_frame_ = nullptr;
        }
        if (microphone_encoder_ctx_) {
            avcodec_free_context(&microphone_encoder_ctx_);
            microphone_encoder_ctx_ = nullptr;
        }
        if (microphone_output_ctx_) {
            if (!(microphone_output_ctx_->oformat->flags & AVFMT_NOFILE) && microphone_output_ctx_->pb) {
                avio_closep(&microphone_output_ctx_->pb);
            }
            avformat_free_context(microphone_output_ctx_);
            microphone_output_ctx_ = nullptr;
        }
        /*if (microphone_out_stream_) {
            av_free(microphone_out_stream_);
        }*/ // 这个流属于前面 microphone_output_ctx_ 内的，不用手动释放
        if (microphone_input_ctx_) {
            avformat_close_input(&microphone_input_ctx_);
            microphone_input_ctx_ = nullptr;
        }
        if (microphone_swr_ctx_) {
            swr_free(&microphone_swr_ctx_);
            microphone_swr_ctx_ = nullptr;
        }
    }


    start_pts_ = 0;
}
